package app.r_teenus.backend.dao;

import java.util.HashSet;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import app.r_teenus.backend.model.Customer;
import app.r_teenus.backend.model.Employee;
import app.r_teenus.backend.model.Enterprise;
import app.r_teenus.backend.model.Person;
import app.r_teenus.backend.model.Search;
import app.r_teenus.backend.model.ServiceRequest;
import app.r_teenus.backend.model.SubjectType;

@Repository("searchtDao")
@Transactional(readOnly = true)
public class SearchDaoImpl extends DefaultDaoImpl implements SearchDao {

	public Search createSearch() {
		Search search = new Search();
		SubjectType defaultType = new SubjectType(-1, "All");
		search.setSubjectTypeList(findSubjectTypes());
		search.getSubjectTypeList().add(0, defaultType);
		return search;
	}

	@SuppressWarnings("unchecked")
	public Search search(Search search) {

		search.getPersons().clear();
		search.getEnterprises().clear();
		search.getEmployees().clear();
		
		if (search.getSubjectTypeId() == 1 || search.getSubjectTypeId() == -1 || search.getSubjectTypeId() == 4) {
			DetachedCriteria criteria = DetachedCriteria.forClass(Person.class);
			if (!search.getFirstName().isEmpty()) {
				criteria.add(Restrictions.eq("firstName", search.getFirstName()));
			}
			if (!search.getName().isEmpty()) {
				criteria.add(Restrictions.eq("lastName", search.getName()));
			}

			boolean addressFilled = false;//, attributeFilled = false;
			if (!search.getCountry().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.country", search.getCountry())));
				addressFilled = true;
			}
			if (!search.getState().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.county", search.getState())));
				addressFilled = true;
			}
			if (!search.getCity().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.townVillage", search.getCity())));
				addressFilled = true;
			}
			if (!search.getAddress().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.streetAddress", search.getAddress())));
				addressFilled = true;
			}
			if (!search.getIndex().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.zipCode", search.getIndex())));
				addressFilled = true;
			}
//			if (!search.getHobby().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueText", search.getHobby())));
//				attributeFilled = true;
//			}
//			if (!search.getDiscount().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueNumber", search.getHobby())));
//				attributeFilled = true;
//			}

			if (addressFilled)
				criteria.createAlias("addresses", "address");
//			if (attributeFilled)
//				criteria.createAlias("subjectAttributes", "att");

			if (!search.getKont().isEmpty()) {
				criteria.createAlias("contacts", "contact");
				criteria.add(Restrictions.disjunction().add(Restrictions.like("contact.valueText", search.getKont())));
			}
			hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("CUSTOMER_TYPE").setParameter("CUSTOMER_TYPE", 1);
			search.setPersons(new HashSet<Person>(hibernateTemplate.findByCriteria(criteria)));
			
			for ( Person pers: search.getPersons()){
				List<Customer> cus = pers.getCustomer();
				if ( cus.size() > 0){
					criteria = DetachedCriteria.forClass(ServiceRequest.class);
					criteria.createAlias("customer", "customer");
					criteria.add(Restrictions.disjunction().add(Restrictions.eq("customer", pers.getCustomer().get(0))));
					if(hibernateTemplate.findByCriteria(criteria).isEmpty()){
						pers.setCanRemove(true);
					}
				}else{
					pers.setCanRemove(true);
				}
			}
		}

		if (search.getSubjectTypeId() == 2 || search.getSubjectTypeId() == -1 || search.getSubjectTypeId() == 4) {

			DetachedCriteria criteria = DetachedCriteria.forClass(Enterprise.class);
			boolean addressFilled = false;//, attributeFilled = false;
			if (!search.getName().isEmpty()) {
				criteria.add(Restrictions.eq("name", search.getName()));
			}
			if (!search.getCountry().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.country", search.getCountry())));
				addressFilled = true;
			}
			if (!search.getState().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.county", search.getState())));
				addressFilled = true;
			}
			if (!search.getCity().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.townVillage", search.getCity())));
				addressFilled = true;
			}
			if (!search.getAddress().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.streetAddress", search.getAddress())));
				addressFilled = true;
			}
			if (!search.getIndex().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.zipCode", search.getIndex())));
				addressFilled = true;
			}
//			if (!search.getHobby().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueText", search.getHobby())));
//				attributeFilled = true;
//			}
//			if (!search.getDiscount().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueNumber", search.getHobby())));
//				attributeFilled = true;
//			}

			if (addressFilled)
				criteria.createAlias("addresses", "address");
//			if (attributeFilled)
//				criteria.createAlias("subjectAttributes", "att");

			if (!search.getKont().isEmpty()) {
				criteria.createAlias("contacts", "contact");
				criteria.add(Restrictions.disjunction().add(Restrictions.like("contact.valueText", search.getKont())));
			}
			hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("ENT_CUSTOMER_TYPE").setParameter("ENT_CUSTOMER_TYPE", 2);
			search.setEnterprises(new HashSet<Enterprise>(hibernateTemplate.findByCriteria(criteria)));
			
			for ( Enterprise ent: search.getEnterprises()){
				List<Customer> cus = ent.getCustomer();
				if ( cus.size() > 0){
					criteria = DetachedCriteria.forClass(ServiceRequest.class);
					criteria.createAlias("customer", "customer");
					criteria.add(Restrictions.disjunction().add(Restrictions.eq("customer", ent.getCustomer().get(0))));
					if(hibernateTemplate.findByCriteria(criteria).isEmpty()){
						ent.setCanRemove(true);
					}
				}else{
					ent.setCanRemove(true);
				}
			}
		}

		if (search.getSubjectTypeId() == 3) {
			DetachedCriteria criteria = DetachedCriteria.forClass(Employee.class);
			criteria.createAlias("person", "person");
			if (!search.getFirstName().isEmpty()) {
				criteria.add(Restrictions.eq("person.firstName", search.getFirstName()));
			}
			if (!search.getName().isEmpty()) {
				criteria.add(Restrictions.eq("person.lastName", search.getName()));
			}

			boolean addressFilled = false;//, attributeFilled = false;
			if (!search.getCountry().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.country", search.getCountry())));
				addressFilled = true;
			}
			if (!search.getState().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.county", search.getState())));
				addressFilled = true;
			}
			if (!search.getCity().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.townVillage", search.getCity())));
				addressFilled = true;
			}
			if (!search.getAddress().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.streetAddress", search.getAddress())));
				addressFilled = true;
			}
			if (!search.getIndex().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.zipCode", search.getIndex())));
				addressFilled = true;
			}
//			if (!search.getHobby().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueText", search.getHobby())));
//				attributeFilled = true;
//			}
//			if (!search.getDiscount().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueNumber", search.getHobby())));
//				attributeFilled = true;
//			}

			if (addressFilled)
				criteria.createAlias("person.addresses", "address");
//			if (attributeFilled)
//				criteria.createAlias("person.subjectAttributes", "att");

			if (!search.getKont().isEmpty()) {
				criteria.createAlias("person.contacts", "contact");
				criteria.add(Restrictions.disjunction().add(Restrictions.like("contact.valueText", search.getKont())));
			}
			
			// enterprise 
			
			if (!search.getName().isEmpty()) {
				criteria.add(Restrictions.eq("enterprise.name", search.getName()));
			}
			if (!search.getCountry().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.country", search.getCountry())));
				addressFilled = true;
			}
			if (!search.getState().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.county", search.getState())));
				addressFilled = true;
			}
			if (!search.getCity().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.townVillage", search.getCity())));
				addressFilled = true;
			}
			if (!search.getAddress().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.streetAddress", search.getAddress())));
				addressFilled = true;
			}
			if (!search.getIndex().isEmpty()) {
				criteria.add(Restrictions.disjunction().add(Restrictions.like("address.zipCode", search.getIndex())));
				addressFilled = true;
			}
//			if (!search.getHobby().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueText", search.getHobby())));
//				attributeFilled = true;
//			}
//			if (!search.getDiscount().isEmpty()) {
//				criteria.add(Restrictions.disjunction().add(Restrictions.like("att.valueNumber", search.getHobby())));
//				attributeFilled = true;
//			}

			if (addressFilled)
				criteria.createAlias("enterprise.addresses", "address");
//			if (attributeFilled)
//				criteria.createAlias("enterprise.subjectAttributes", "att");

			if (!search.getKont().isEmpty()) {
				criteria.createAlias("enterprise.contacts", "contact");
				criteria.add(Restrictions.disjunction().add(Restrictions.like("contact.valueText", search.getKont())));
			}
			
			search.setEmployees(hibernateTemplate.findByCriteria(criteria));
		}
		
//		 if (search.getSubjectTypeId() == 4 || search.getSubjectTypeId() == -1) {
//		
//		 String personQuery = "SELECT * FROM PERSON  INNER JOIN CUSTOMER ON customer.subject_fk=person.person and customer.SUBJECT_TYPE_FK = 1 ";
//		
//		 String enterpriseQuery = "SELECT * FROM ENTERPRISE  INNER JOIN CUSTOMER ON customer.subject_fk=enterprise.enterprise and customer.SUBJECT_TYPE_FK = 2 ";
//		
//		 boolean addressFilled = false;//, attributeFilled = false;
//		 if (!search.getFirstName().isEmpty()) {
//		 personQuery = personQuery + " and person.first_name = " + "\'" + search.getFirstName() + "\'";
//		 }
//		 if (!search.getName().isEmpty()) {
//		 personQuery =personQuery +" and person.last_name = " + "\'" + search.getName() + "\'";
//		 }
//		 if (!search.getName().isEmpty()) {
//		 enterpriseQuery =enterpriseQuery +" and enterprise.name = " + "\'" + search.getName() + "\'";
//		 }
//		 String addressQuery = "";
//		 String attributeQuery = "";
//		 if (!search.getCountry().isEmpty()) {
//		 addressQuery = addressQuery +" and address.country like " + "\'%" + search.getCountry() + "%\'";
//		 addressFilled = true;
//		 }
//		 if (!search.getState().isEmpty()) {
//		 addressQuery = addressQuery +" and address.county like " + "\'%" + search.getState() + "%\'";
//		 addressFilled = true;
//		 }
//		 if (!search.getCity().isEmpty()) {
//		 addressQuery = addressQuery +" and address.TOWN_VILLAGE like " + "\'%" + search.getCity() + "%\'";
//		 addressFilled = true;
//		 }
//		 if (!search.getAddress().isEmpty()) {
//		 addressQuery = addressQuery +" and address.STREET_ADDRESS like " + "\'%" + search.getAddress() + "%\'";
//		 addressFilled = true;
//		 }
//		 if (!search.getIndex().isEmpty()) {
//		 addressQuery = addressQuery +" and address.ZIPCODE like " + "\'%" + search.getIndex() + "%\'";
//		 addressFilled = true;
//		 }
////		 if (!search.getHobby().isEmpty()) {
////		 attributeQuery = attributeQuery +" and att.VALUE_TEXT like " + "\'%" + search.getHobby() + "%\'";
////		 attributeFilled = true;
////		 }
////		 if (!search.getDiscount().isEmpty()) {
////		 attributeQuery = attributeQuery +" and att.VALUE_NUMBER like " + "\'%" + search.getDiscount() + "%\'";
////		 attributeFilled = true;
////		 }
////		
////		 if (attributeFilled) {
////		 personQuery += " INNER JOIN SUBJECT_ATTRIBUTE att ON att.subject_fk=person.person and  att.SUBJECT_TYPE_FK = 1 " + attributeQuery;
////		 enterpriseQuery += " INNER JOIN SUBJECT_ATTRIBUTE att ON att.subject_fk=enterprise.enterprise and  att.SUBJECT_TYPE_FK = 2 " + attributeQuery;
////		 }
//		
//		 if (!search.getKont().isEmpty()) {
//		 personQuery += " INNER JOIN CONTACT con ON con.subject_fk=person.person and  att.SUBJECT_TYPE_FK = 1 and con.VALUE_TEXT  like " + "\'%" + search.getKont() + " %\'";
//		 enterpriseQuery += " INNER JOIN CONTACT con ON con.subject_fk=enterprise.enterprise and  att.SUBJECT_TYPE_FK = 2 and con.VALUE_TEXT  like " + "\'%" + search.getKont() + " %\'";
//		 }
//		
//		 if (addressFilled) {
//		 personQuery += " INNER JOIN ADDRESS address ON address.subject_fk=person.person  and address.SUBJECT_TYPE_FK = 1 " + addressQuery;
//		 enterpriseQuery += " INNER JOIN ADDRESS address ON address.subject_fk=enterprise.enterprise  and address.SUBJECT_TYPE_FK = 2 " + addressQuery;
//		 }
//		
//		 search.setEnterprises(new HashSet<Enterprise>(hibernateTemplate.getSessionFactory().getCurrentSession().createSQLQuery(enterpriseQuery).addEntity("enterprise", Enterprise.class).list())); // addJoin("person.address", "address")
////		 search.setPersons(new HashSet<Person>(hibernateTemplate.getSessionFactory().getCurrentSession().createSQLQuery(personQuery).addEntity("person", Person.class).list()));
//		
//		 }

		return search;
	}
}
